package top.glike.ssl.auto.service.impl;

import cn.hutool.core.io.FileUtil;
import com.aliyun.auth.credentials.Credential;
import com.aliyun.auth.credentials.provider.StaticCredentialProvider;
import com.aliyun.sdk.service.cas20200407.AsyncClient;
import com.aliyun.sdk.service.cas20200407.models.*;
import com.google.gson.Gson;
import darabonba.core.client.ClientOverrideConfiguration;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import top.glike.ssl.auto.domain.SslCloudProvider;
import top.glike.ssl.auto.domain.SslDomainCertificate;
import top.glike.ssl.auto.domain.other.AutoSslDomain;
import top.glike.ssl.auto.domain.other.CertInfo;
import top.glike.ssl.auto.domain.other.CloudCertInfo;
import top.glike.ssl.auto.mapper.AutoSslConfMapper;
import top.glike.ssl.auto.service.IAutoSslConfService;
import top.glike.ssl.auto.service.ISslCloudProviderService;
import top.glike.ssl.auto.service.ISslDomainCertificateService;
import top.glike.ssl.common.utils.email.EmailUtil;

import java.io.File;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

@Slf4j
@Service
public class AutoSslConfServiceImpl implements IAutoSslConfService {

    private final Map<String, AsyncClient> clientMap = new HashMap<>();

    @Autowired
    private EmailUtil emailUtil;
    @Autowired
    private ISslCloudProviderService cloudProviderService;
    @Autowired
    private ISslDomainCertificateService domainCertificateService;
    @Autowired
    private AutoSslConfMapper autoSslConfMapper;
    @Autowired
    private CertificateDeploymentService deploymentService;

    @Override
    public void testCert() {
        log.info("查询所有启用的证书信息...");

        try {
            log.info("拉取云端域名SSL信息...");

            // 查询所有域名信息
            // List<SslDomainCertificate> domainAllList = domainCertificateService.selectSslDomainCertificateList(null);

            /*List<AutoSslDomain> domainList = autoSslConfMapper.queryNeedAutoRenewCertList();
            if (domainList != null && !domainList.isEmpty()) {
                log.info("共查询到{}条已启用的证书信息...", domainList.size());
                log.info("开始检测并从云端拉取同步域名信息....");
                for (AutoSslDomain sslInfo : domainList) {
                    if (StringUtils.isAnyBlank(sslInfo.getCertificateId(), sslInfo.getOrderId(), sslInfo.getProductCode())
                            || Objects.isNull(sslInfo.getIssueTime()) || Objects.isNull(sslInfo.getExpireTime())) {
                        log.info("检测到域名{}的数据不全, 则需从云端同步到本地...", sslInfo.getDomainName());

                        SslDomainCertificate domain = domainCertificateService.getDomainByDomainName(sslInfo.getDomainName());
                        // 核对云上是否需要续期
                        CertInfo certInfo = this.getCloudCertInfo(sslInfo);
                        domain.setCertificateId(String.valueOf(certInfo.getCertId()));
                        domain.setStatus(certInfo.getStatus());
                        domain.setOrderId(String.valueOf(certInfo.getOrderId()));
                        domain.setProductCode(certInfo.getProductName());
                        domain.setIssueTime(certInfo.getCertStartTime());
                        domain.setExpireTime(certInfo.getCertEndTime());
                        domainCertificateService.updateSslDomainCertificate(domain);
                    }
                }

                // 更新数据
                domainList = autoSslConfMapper.queryNeedAutoRenewCertList();
                if (domainList != null && !domainList.isEmpty()) {
                    log.info("共查询到{}条已启用的证书信息...", domainList.size());
                    log.info("开始检测并匹配当前是否需要自动续费....");
                    for (AutoSslDomain sslInfo : domainList) {
                        String domainName = sslInfo.getDomainName();
                        Boolean autoRenew = sslInfo.getAutoRenew(); // 是否字段续期
                        Long renewBeforeDays = sslInfo.getRenewBeforeDays(); // 过期前?天续期
                        Date expireTime = sslInfo.getExpireTime(); // 过期时间
                        String expiryStatusDescription = sslInfo.getExpiryStatusDescription(); // 状态描述
                        Boolean isNearExpiry = sslInfo.checkNearExpiry(); // 是否近期过期
                        Boolean expired = sslInfo.isExpired(); // 是否已过期
                        Boolean deleteOldCert = sslInfo.getDeleteOldCert(); // 续期后是否删除即将过期或已过期的记录
                        log.info("域名{} - {}, 是否已过期:{}, 过期时间:{}, 是否支持自动续期:{}, 过期前{}天自动续期, 续期成功后是否自动移除即将过期的证书信息:{}", domainName, expiryStatusDescription, expired, expireTime, autoRenew, renewBeforeDays != null ? renewBeforeDays : 2, deleteOldCert);
                        // 近期过期且配置自动续期
                        if (isNearExpiry && autoRenew) {
                            // 申请续期
                            // 先查询客户端, 查不到则创建客户端
                            AsyncClient connectClient = this.getConnectClient(sslInfo.getMainDomain());
                            if (connectClient == null) {
                                this.createClient(sslInfo);
                            }
                            // 核对云上是否需要续期
                            CertInfo certInfo = this.getCloudCertInfo(sslInfo);
                            if (certInfo.isExpired() || certInfo.isNearExpiry()) {
                                // 开始续期
                                sslInfo = this.createCertInfo(sslInfo);
                                CloudCertInfo cloudStatus = null;
                                // 循环查询订单申请是否成功
                                String statusFlag = "";
                                do {
                                    Thread.sleep(3000);
                                    cloudStatus = this.queryApplyCertStatus(sslInfo);
                                    statusFlag = cloudStatus.getApplyStatus();
                                    log.info("查询证书{}的申请状态: {}", sslInfo.getOrderId(), statusFlag);
                                } while (StringUtils.equalsAny(statusFlag, "success", "fail"));
                                if (StringUtils.equals(statusFlag, "fail")) {
                                    log.info("申请失败...");
                                } else {
                                    // 申请成功，继续操作
                                    sslInfo.setCertificate(cloudStatus.getCertificate());
                                    sslInfo.setPrivateKey(cloudStatus.getPrivateKey());
                                    // 下载key和pem文件到指定目录
                                    this.saveCertificateFiles(sslInfo);
                                    // 续期成功-部署到对应服务器端
                                    deploymentService.uploadFile(sslInfo);
                                    deploymentService.executeCommand(sslInfo, "nginx -s reload");
                                    // 同时是否删除云上老记录和表记录禁用

                                }
                            }
                        }
                    }
                }
            }*/
        } catch (Exception e) {
            log.error("核对续期出现异常: {}", e.getMessage());
            log.error(e.getMessage(), e);
        } finally {
            this.closeAllClient();
        }
    }

    /**
     * 创建证书
     *
     * @param domain 域名
     */
    @Override
    public void createCert(String domain) {
        log.info("申请创建新证书...");
        try {
            AutoSslDomain sslInfo = autoSslConfMapper.queryNeedAutoRenewCertByDomainName(domain);
            if (!Objects.isNull(sslInfo)) {
                String domainName = sslInfo.getDomainName();
                Boolean autoRenew = sslInfo.getAutoRenew(); // 是否字段续期
                Long renewBeforeDays = sslInfo.getRenewBeforeDays(); // 过期前?天续期
                Date expireTime = sslInfo.getExpireTime(); // 过期时间
                String expiryStatusDescription = sslInfo.getExpiryStatusDescription(); // 状态描述
                Boolean isNearExpiry = sslInfo.checkNearExpiry(); // 是否近期过期
                Boolean expired = sslInfo.isExpired(); // 是否已过期
                Boolean deleteOldCert = sslInfo.getDeleteOldCert(); // 续期后是否删除即将过期或已过期的记录
                log.info("域名{} - {}, 是否已过期:{}, 过期时间:{}, 是否支持自动续期:{}, 过期前{}天自动续期, 续期成功后是否自动移除即将过期的证书信息:{}", domainName, expiryStatusDescription, expired, expireTime, autoRenew, renewBeforeDays != null ? renewBeforeDays : 2, deleteOldCert);
                // 近期过期且配置自动续期
                if (isNearExpiry && autoRenew) {
                    // 申请续期
                    // 核对云上是否需要续期
                    CertInfo certInfo = this.getCloudCertInfo(sslInfo);
                    if (certInfo.isExpired() || certInfo.isNearExpiry()) {
                        // 开始续期
                        sslInfo = this.createCertInfo(sslInfo);
                        SslDomainCertificate domainInfo = domainCertificateService.getDomainByDomainName(domainName);
                        domainInfo.setOrderId(sslInfo.getOrderId());
                        domainCertificateService.saveSslDomainCertificate(domainInfo);
                        CloudCertInfo cloudStatus = null;
                        // 循环查询订单申请是否成功
                        String statusFlag = "";
                        do {
                            Thread.sleep(3000);
                            cloudStatus = this.queryApplyCertStatus(sslInfo);
                            statusFlag = cloudStatus.getApplyStatus();
                            log.info("查询证书{}的申请状态: {}", sslInfo.getOrderId(), statusFlag);
                        } while (StringUtils.equalsAny(statusFlag, "success", "fail"));
                        if (StringUtils.equals(statusFlag, "fail")) {
                            log.info("申请失败...");
                        } else {
                            // 申请成功，继续操作
                            // 更新最新证书信息到数据表中
                            sslInfo.setCertificate(cloudStatus.getCertificate());
                            sslInfo.setPrivateKey(cloudStatus.getPrivateKey());
                            // 获取证书信息，并保存
                            domainInfo = domainCertificateService.getDomainByDomainName(domainName);
                            domainInfo.setCertificatePem(cloudStatus.getCertificate());
                            domainInfo.setPrivateKey(cloudStatus.getPrivateKey());
                            domainCertificateService.updateSslDomainCertificate(domainInfo);
                            // 下载key和pem文件到指定目录
                            this.saveCertificateFiles(sslInfo);
                            if (StringUtils.isAnyBlank(sslInfo.getIpAddress(),
                                    String.valueOf(sslInfo.getSshPort()),
                                    sslInfo.getUsername(),
                                    sslInfo.getPassword())) {
                                log.info("服务器信息配置不全, 请配置后再重试...");
                                // 发送邮件提示
                                emailUtil.sendMessage(sslInfo.getEmail(),
                                        "服务器信息配置缺失",
                                        String.format("<h4>请配置域名:<a href=\"https://%s\">%s</a>的<span style=\"color: red\">服务器配置</span>信息, 以保证可以顺利更换证书!</h4>",
                                                sslInfo.getDomainName(),
                                                sslInfo.getDomainName())
                                );
                            } else {
                                // 续期成功-部署到对应服务器端
                                deploymentService.uploadFile(sslInfo);
                                deploymentService.executeCommand(sslInfo, "nginx -s reload");
                            }
                            // 同时是否删除云上老记录和表记录禁用
                            // 删除云上老记录
                            if (domainInfo.getDeleteOldCert() == 1) {
                                this.deleteCertInfo(sslInfo);
                            }
                            // 数据同步到表数据中...
                            this.syncCloudCertToLocal(domainName);
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("申请证书出现异常: {}", e.getMessage());
            log.error(e.getMessage(), e);
        }

    }

    @Override
    public void syncCloudCertToLocal(String domainName) {
        try {
            log.info("拉取云端域名SSL信息...");
            SslCloudProvider sslCloud = new SslCloudProvider();
            sslCloud.setStatus(1);
            if (StringUtils.isNotBlank(domainName)) {
                SslDomainCertificate domain = domainCertificateService.getDomainByDomainName(domainName);
                sslCloud.setId(domain.getCloudProviderId());
            }
            List<SslCloudProvider> cloudList = cloudProviderService.selectSslCloudProviderList(sslCloud);
            Map<String, CertInfo> certMap = new HashMap<>();
            if (cloudList != null && !cloudList.isEmpty()) {
                log.info("需要检测{}个云上数据", cloudList.size());
                cloudList.forEach(cloud -> {
                    String accessKeyId = cloud.getAccessKeyId();
                    String accessKeySecret = cloud.getAccessKeySecret();
                    String regionId = cloud.getRegionId();
                    List<CertInfo> certList = this.getAllCertInfoByCloud(accessKeyId, accessKeySecret, regionId);

                    if (certList != null && !certList.isEmpty()) {
                        log.info("-----处理后的数据-----");
                        certList.stream().sorted(Comparator.comparing(CertInfo::getCertEndTime)).forEach(cert -> {
                            certMap.put(cert.getDomain(), cert);
                        });
                        certMap.forEach((key, cert) -> {
                            log.info("{}---> {}", key, cert);
                            SslDomainCertificate domainInfo = domainCertificateService.getDomainByDomainName(cert.getDomain());
                            if (domainInfo != null) {
                                domainInfo.setNewCertInfo(cert);
                            } else {
                                AutoSslDomain sslDomain = new AutoSslDomain();
                                sslDomain.setAccessKeyId(accessKeyId);
                                sslDomain.setAccessKeySecret(accessKeySecret);
                                sslDomain.setRegionId(regionId);
                                sslDomain.setCertificateId(String.valueOf(cert.getCertId()));
                                // 获取云上证书pem和key信息
                                CertInfo cloudCertInfo = this.getCloudCertInfo(sslDomain);
                                domainInfo = new SslDomainCertificate(cert, cloud.getId());
                                domainInfo.setCertificatePem(cloudCertInfo.getCertificatePem());
                                domainInfo.setPrivateKey(cloudCertInfo.getPrivateKey());
                            }
                            domainCertificateService.saveSslDomainCertificate(domainInfo);
                        });
                    } else {
                        log.info("获取到云端数据为空...");
                    }
                });
            }
        } catch (Exception e) {
            log.error("拉取云端数据到本地数据库出现异常: {}", e.getMessage());
            log.error(e.getMessage(), e);
        } finally {
            this.closeAllClient();
        }
    }

    /**
     * 保存证书文件（pem和key）
     */
    public void saveCertificateFiles(AutoSslDomain sslDomain) {
        try {
            // 将域名中的"."替换为"_"
            String safeDomainName = sslDomain.getCertFileName();
            String domainDir = sslDomain.getCertLocalPath() + safeDomainName;

            // 创建域名目录
            File dir = new File(domainDir);
            if (!dir.exists()) {
                dir.mkdirs();
            }

            // 保存证书文件 (.pem) - 使用安全的域名格式
            String certFilePath = domainDir + File.separator + safeDomainName + ".pem";
            FileUtil.writeUtf8String(sslDomain.getCertificate(), certFilePath);

            // 保存私钥文件 (.key) - 使用安全的域名格式
            String keyFilePath = domainDir + File.separator + safeDomainName + ".key";
            FileUtil.writeUtf8String(sslDomain.getPrivateKey(), keyFilePath);

            log.info("证书文件已保存到目录: {}", domainDir);
            log.info("证书文件: {}", certFilePath);
            log.info("私钥文件: {}", keyFilePath);
            sslDomain.setCertFile(certFilePath);
            sslDomain.setKeyFile(keyFilePath);

        } catch (Exception e) {
            log.error("保存证书文件失败: " + e.getMessage(), e);
            throw new RuntimeException("保存证书文件失败: " + e.getMessage(), e);
        }
    }

    /**
     * 拉取云上证书信息
     *
     * @param sslDomain 配置信息
     * @return
     * @throws Exception
     */
    public CertInfo getCloudCertInfo(AutoSslDomain sslDomain) {
        try {
            // Parameter settings for API request
            GetUserCertificateDetailRequest getUserCertificateDetailRequest = GetUserCertificateDetailRequest.builder()
                    .certFilter(false)
                    .certId(Long.valueOf(sslDomain.getCertificateId()))
                    .build();

            // Asynchronously get the return value of the API request
            CompletableFuture<GetUserCertificateDetailResponse> response = this.getConnectClient(sslDomain).getUserCertificateDetail(getUserCertificateDetailRequest);

            // Synchronously get the return value of the API request
            GetUserCertificateDetailResponse resp = response.get();
            GetUserCertificateDetailResponseBody body = resp.getBody();
            CertInfo certInfo = new CertInfo();
            certInfo.setDomain(body.getCommon());
            certInfo.setAlgorithm(body.getAlgorithm());
            certInfo.setOrderId(body.getOrderId());
            certInfo.setCertId(body.getId());
            certInfo.setProductName(body.getName());
            certInfo.setCertEndTime(new Date(body.getNotAfter()));
            certInfo.setCertStartTime(new Date(body.getNotBefore()));
            certInfo.checkNearExpiry(Math.toIntExact(sslDomain.getRenewBeforeDays()));
            certInfo.setStatusByCloud(body.getExpired());
            certInfo.setCertificatePem(body.getCert());
            certInfo.setPrivateKey(body.getKey());
            log.info(certInfo.toString());
            return certInfo;
        } catch (Exception e) {
            log.error("拉取云上证书信息出现异常: {}", e.getMessage());
            log.error(e.getMessage(), e);
            throw new RuntimeException("拉取云上证书信息出现异常");
        }
    }

    @Override
    public int pushCertToServer(Long id) {
        try {
            AutoSslDomain sslDomain = autoSslConfMapper.queryReConfInfoByDomainId(id);
            deploymentService.uploadFile(sslDomain);
            deploymentService.executeCommand(sslDomain, sslDomain.getNginxReloadCmd());
            return 1;
        } catch (Exception e) {
            log.error("推送文件并执行命令出现异常: {}", e.getMessage());
            log.error(e.getMessage(), e);
        }
        return 0;
    }

    /**
     * TODO 页面实现手动推送证书到服务器指定目录并重启nginx程序
     * 整理可供下载和部署的文件类型，实现推送时选择类型进行推送（下载功能也是）
     * 文件后缀名，需要导入到字典中，并从字典中获取后生成文件后导入进去即可。
     * （先查询生成的是否有，有就用；没有就重新生成，根据上次同步的时间判断）
     * 设置证书文件的名称，后缀从字典取，下载或推送时拼接搞定即可
     *
     */

    /**
     * 申请创建证书
     *
     * @param sslDomain 配置信息
     * @return 证书订单id
     * @throws Exception
     */
    public AutoSslDomain createCertInfo(AutoSslDomain sslDomain) throws Exception {
        // Parameter settings for API request
        CreateCertificateRequestRequest createCertificateRequestRequest = CreateCertificateRequestRequest.builder()
                // .productCode("digicert-free-1-free")
                .productCode(sslDomain.getProductCode())
                .username(sslDomain.getCertUsername())
                .phone(sslDomain.getPhone())
                .email(sslDomain.getEmail())
                .domain(sslDomain.getDomainName())
                .validateType(sslDomain.getValidateType())
                .build();

        // Asynchronously get the return value of the API request
        CompletableFuture<CreateCertificateRequestResponse> response = getConnectClient(sslDomain.getAccessKeyId()).createCertificateRequest(createCertificateRequestRequest);
        // Synchronously get the return value of the API request
        CreateCertificateRequestResponse resp = response.get();
        String json = new Gson().toJson(resp);
        log.info(json);
        log.info("-----创建生成csr内容的证书响应-----");
        CreateCertificateRequestResponseBody body = resp.getBody();
        Long orderId = body.getOrderId();
        log.info("orderId: {}", orderId);
        sslDomain.setOrderId(String.valueOf(orderId));
        return sslDomain;
    }

    /**
     * 删除证书信息
     *
     * @param sslDomain 配置信息
     * @throws Exception
     */
    public void deleteCertInfo(AutoSslDomain sslDomain) throws Exception {
        // Parameter settings for API request
        DeleteUserCertificateRequest deleteUserCertificateRequest = DeleteUserCertificateRequest.builder()
                .certId(Long.valueOf(sslDomain.getCertificateId()))
                // Request-level configuration rewrite, can set Http request parameters, etc.
                // .requestConfiguration(RequestConfiguration.create().setHttpHeaders(new HttpHeaders()))
                .build();

        // Asynchronously get the return value of the API request
        CompletableFuture<DeleteUserCertificateResponse> response = getConnectClient(sslDomain).deleteUserCertificate(deleteUserCertificateRequest);
        // Synchronously get the return value of the API request
        DeleteUserCertificateResponse resp = response.get();
        String json = new Gson().toJson(resp);
        log.info("-----删除证书响应-----");
        log.info(json);
    }

    /**
     * 查询申请的证书状态
     *
     * @param sslDomain 配置信息
     * @return 成功或失败
     * @throws Exception
     */
    public CloudCertInfo queryApplyCertStatus(AutoSslDomain sslDomain) throws Exception {
        // Parameter settings for API request
        DescribeCertificateStateRequest describeCertificateStateRequest = DescribeCertificateStateRequest.builder()
                .orderId(Long.valueOf(sslDomain.getOrderId()))
                .build();

        // Asynchronously get the return value of the API request
        CompletableFuture<DescribeCertificateStateResponse> response = getConnectClient(sslDomain).describeCertificateState(describeCertificateStateRequest);
        // Synchronously get the return value of the API request
        DescribeCertificateStateResponse resp = response.get();
        DescribeCertificateStateResponseBody body = resp.getBody();
        log.info("查询证书申请结果：{}", body);
        CloudCertInfo cloudCertInfo = new CloudCertInfo(body);
        return cloudCertInfo;
    }

    /**
     * 创建SSL服务
     *
     * @param key 唯一标识
     * @return
     */
    public AsyncClient getConnectClient(String key) {
        return clientMap.get(key);
    }

    /**
     * 获取SSL服务
     *
     * @param sslDomain 唯一标识
     * @return
     */
    public AsyncClient getConnectClient(AutoSslDomain sslDomain) {
        AsyncClient asyncClient = clientMap.get(sslDomain.getAccessKeyId());
        if (asyncClient == null) {
            createClient(sslDomain);
        }
        asyncClient = clientMap.get(sslDomain.getAccessKeyId());
        return asyncClient;
    }

    /**
     * 初始化SSL服务
     *
     * @param sslDomain 配置信息
     */
    public void createClient(AutoSslDomain sslDomain) {
        // 创建SSL证书服务
        StaticCredentialProvider provider = StaticCredentialProvider.create(Credential.builder()
                .accessKeyId(sslDomain.getAccessKeyId())
                .accessKeySecret(sslDomain.getAccessKeySecret())
                .build());
        // 创建客户端
        AsyncClient client = AsyncClient.builder()
                .region(sslDomain.getRegionId()) // Region ID
                // .region("cn-hangzhou") // Region ID
                .credentialsProvider(provider)
                .overrideConfiguration(ClientOverrideConfiguration.create().setEndpointOverride("cas.aliyuncs.com"))
                .build();
        clientMap.put(sslDomain.getAccessKeyId(), client);
    }

    /**
     * 关闭服务
     *
     * @param key 唯一key
     */
    public void closeClient(String key) {
        clientMap.get(key).close();
    }

    /**
     * 关闭所有客户端链接
     */
    public void closeAllClient() {
        clientMap.forEach((key, value) -> value.close());
    }

    /**
     * 获取所有的证书信息
     *
     * @return
     */
    public List<CertInfo> getAllCertInfo(AutoSslDomain sslDomain) {
        List<CertInfo> certList = new ArrayList<>();
        try {
            ListUserCertificateOrderRequest listUserCertificateOrderRequest = ListUserCertificateOrderRequest.builder()
                    .build();

            // Asynchronously get the return value of the API request
            CompletableFuture<ListUserCertificateOrderResponse> response = getConnectClient(sslDomain).listUserCertificateOrder(listUserCertificateOrderRequest);

            // Synchronously get the return value of the API request
            ListUserCertificateOrderResponse resp = response.get();
            String json = new Gson().toJson(resp);
            log.info(json);
            ListUserCertificateOrderResponseBody body = resp.getBody();
            List<ListUserCertificateOrderResponseBody.CertificateOrderList> list = body.getCertificateOrderList();
            log.info("-----查询证书列表数据-----");
            for (ListUserCertificateOrderResponseBody.CertificateOrderList info : list) {
                CertInfo certInfo = new CertInfo();
                certInfo.setCertId(info.getCertificateId());
                certInfo.setDomain(info.getDomain());
                certInfo.setProductCode(info.getProductCode());
                certInfo.setStatus(info.getStatus());
                certInfo.setAlgorithm(info.getAlgorithm());
                certInfo.setOrderId(info.getOrderId());
                certInfo.setProductName(info.getProductName());
                certInfo.setCertEndTime(new Date(info.getCertEndTime()));
                certInfo.setCertStartTime(new Date(info.getCertStartTime()));
                certInfo.setServerId(sslDomain.getServerId());
                certInfo.setCloudProviderId(sslDomain.getCloudProviderId());
                certList.add(certInfo);
                log.info(certInfo.toString());
            }
        } catch (Exception e) {
            log.error("查询并证书列表出现异常：{}", e.getMessage());
            log.error(e.getMessage(), e);
        }
        return certList;
    }

    /**
     * 获取所有的证书信息
     *
     * @return
     */
    public List<CertInfo> getAllCertInfoByCloud(String accessKeyId, String accessKeySecret, String regionId) {
        List<CertInfo> certList = new ArrayList<>();
        try {
            ListUserCertificateOrderRequest listUserCertificateOrderRequest = ListUserCertificateOrderRequest.builder()
                    .orderType("CERT")
                    .build();

            // Asynchronously get the return value of the API request
            CompletableFuture<ListUserCertificateOrderResponse> response = getConnectClient(accessKeyId, accessKeySecret, regionId).listUserCertificateOrder(listUserCertificateOrderRequest);

            // Synchronously get the return value of the API request
            ListUserCertificateOrderResponse resp = response.get();
            String json = new Gson().toJson(resp);
            log.info(json);
            ListUserCertificateOrderResponseBody body = resp.getBody();
            List<ListUserCertificateOrderResponseBody.CertificateOrderList> list = body.getCertificateOrderList();
            log.info("-----查询证书列表数据-----");
            for (ListUserCertificateOrderResponseBody.CertificateOrderList info : list) {
                CertInfo certInfo = new CertInfo();
                certInfo.setCertId(info.getCertificateId());
                certInfo.setDomain(info.getCommonName());
                certInfo.setStatus(info.getStatus());
                certInfo.setCertEndTime(new Date(info.getCertEndTime()));
                certInfo.setCertStartTime(new Date(info.getCertStartTime()));
                certList.add(certInfo);
                log.info(certInfo.toString());
            }
        } catch (Exception e) {
            log.error("查询并证书列表出现异常：{}", e.getMessage());
            log.error(e.getMessage(), e);
        } finally {
            closeClient(accessKeyId);
        }
        return certList;
    }

    /**
     * 创建SSL服务
     *
     * @param accessKeyId
     * @param accessKeySecret
     * @param regionId
     * @return
     */
    private AsyncClient getConnectClient(String accessKeyId, String accessKeySecret, String regionId) {
        // 创建SSL证书服务
        StaticCredentialProvider provider = StaticCredentialProvider.create(Credential.builder()
                .accessKeyId(accessKeyId)
                .accessKeySecret(accessKeySecret)
                .build());
        // 创建客户端
        AsyncClient client = AsyncClient.builder()
                .region(regionId) // Region ID
                // .region("cn-hangzhou") // Region ID
                .credentialsProvider(provider)
                .overrideConfiguration(ClientOverrideConfiguration.create().setEndpointOverride("cas.aliyuncs.com"))
                .build();
        clientMap.put(accessKeyId, client);
        return client;
    }

    /**
     * 获取所有符合条件需要重新部署的证书信息
     *
     * @return
     */
    public List<CertInfo> getAllNeedRenewCertList() {
        List<CertInfo> certList = this.getAllCertInfo(null);
        List<CertInfo> needRenewCertList = certList.stream().filter(
                cert -> (StringUtils.equals("", cert.getStatus()) && (cert.getDaysToExpire() < 3))
        ).collect(Collectors.toList());
        log.info("获取到符合条件需要重新部署的证书{}条", needRenewCertList.size());
        return needRenewCertList;
    }

}
